﻿namespace System.Diagnostics.Contracts
{
    /// <summary>
    /// Extends the .NET frameworks Code Contracts model.
    /// </summary>
    public static class ContractEx
    {
        /// <summary>
        /// Checks if the given condition is fulfilled and throws an exception of type <b>TEx</b>/>
        /// in case it is not.
        /// </summary>
        /// <typeparam name="TEx">exception type to throw</typeparam>
        /// <param name="condition">condition that need to be fulfilled</param>
        public static void Check<TEx>(bool condition)
            where TEx : Exception, new()
        {
            Check<TEx>(condition, null);
        }

        /// <summary>
        /// Checks if the given condition is fulfilled and throws an exception of type <b>TEx</b>
        /// in case it is not.
        /// </summary>
        /// <typeparam name="TEx">exception type to throw</typeparam>
        /// <param name="condition">>condition that need to be fulfilled</param>
        /// <param name="message">custom exception message</param>
        public static void Check<TEx>(bool condition, string message)
            where TEx : Exception, new()
        {
            Func<bool> f = () => { return condition; };
            Check<TEx>(f, message);
        }

        /// <summary>
        /// Checks if the given condition is fulfilled and throws an exception of type <b>TEx</b>
        /// in case it is not.
        /// </summary>
        /// <typeparam name="TEx">exception type to throw</typeparam>
        /// <param name="condition">condition that need to be fulfilled</param>
        public static void Check<TEx>(Func<bool> condition)
            where TEx : Exception, new()
        {
            Check<TEx>(condition, null);
        }

        /// <summary>
        /// Checks if the given condition is fulfilled and throws an exception of type <b>TEx</b>
        /// in case it is not.
        /// </summary>
        /// <typeparam name="TEx">exception type to throw</typeparam>
        /// <param name="condition">>condition that need to be fulfilled</param>
        /// <param name="message">custom exception message</param>
        public static void Check<TEx>(Func<bool> condition, string message)
            where TEx : Exception, new()
        {
            Contract.Requires<ArgumentNullException>(condition != null, "condition");

            if (condition())
                return;

            TEx ex = new TEx();

            if (!string.IsNullOrEmpty(message))
            {
                try
                {
                    ex = (TEx)Activator.CreateInstance(typeof(TEx), message);
                }
                catch (Exception)
                {
                }
            }
            throw ex;
        }
    }
}